﻿using Farming.Domain;
using IdentityModel;
using Microsoft.AspNetCore.Http;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Diagnostics;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Farming.Application
{
    public sealed class SoftDeleteInterceptor : SaveChangesInterceptor
    {
        private readonly IHttpContextAccessor httpContextAccessor;
        public SoftDeleteInterceptor(HttpContextAccessor httpContextAccessor)
        {
            this.httpContextAccessor = httpContextAccessor;
        }
        public override InterceptionResult<int> SavingChanges(DbContextEventData eventData, InterceptionResult<int> result)
        {
            OnSavingChanges(eventData);
            return base.SavingChanges(eventData, result);
        }
        public override ValueTask<InterceptionResult<int>> SavingChangesAsync(DbContextEventData eventData, InterceptionResult<int> result,
         CancellationToken cancellationToken = new CancellationToken())
        {
            OnSavingChanges(eventData);
            return base.SavingChangesAsync(eventData, result, cancellationToken);
        }
        private void OnSavingChanges(DbContextEventData eventData)
        {
            ArgumentNullException.ThrowIfNull(eventData.Context);
            eventData.Context.ChangeTracker.DetectChanges();

            var cla = httpContextAccessor.HttpContext.User;
            var cusType = "id";
            var userId = int.Parse(cla.FindFirst(cusType)?.Value);
            var userName = cla.FindFirst(JwtClaimTypes.Name)?.Value;
            foreach (var entityEntry in eventData.Context.ChangeTracker.Entries())
                {
                    if (entityEntry.Entity is IAudit audit)
                    {
                        if (entityEntry.State == EntityState.Added)
                        {
                            audit.CreateById = userId;
                            audit.CreateByName = userName;
                            audit.CreateTime = DateTime.UtcNow;
                        }
                        else if (entityEntry.State == EntityState.Modified)
                        {
                            audit.UpdById = userId;
                            audit.UpdByName = userName;
                            audit.UpdTime = DateTime.UtcNow;
                        }
                    }

                    if (entityEntry is { State: EntityState.Deleted, Entity: ISoftDeleteEntityDeleted softDeleteEntity })
                    {
                        softDeleteEntity.IsDel = true;
                        softDeleteEntity.DelById = userId;
                        softDeleteEntity.DelByName = userName;
                        softDeleteEntity.DelTime = DateTime.UtcNow;
                        entityEntry.State = EntityState.Modified;
                    }
            }
        }
    }
}
